package org.springframework.aop.framework;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.springframework.aop.AdvisedSupport;

import java.lang.reflect.Method;
import java.util.List;

/**
 * cglib动态代理
 */
public class CglibAopProxy implements AopProxy {
    //核心对象 包含了需要代理的对象和很多信息
    private final AdvisedSupport advised;

    public CglibAopProxy(AdvisedSupport advised) {
        this.advised = advised;
    }


    @Override
    public Object getProxy() {
        // 创建动态代理增强类
        //这是创建cglib代理对象的工具类
        Enhancer enhancer = new Enhancer();
        //cglib是通过继承来实现动态代理的 需要设置父类 当然有接口的时候 肯定也需要设置接口
        enhancer.setSuperclass(advised.getTargetSource().getTarget().getClass());
        enhancer.setInterfaces(advised.getTargetSource().getTargetClass());
        //设置增强的回调拦截器 这里只能设置cglib包下的方法拦截器
        // 所以下面才要新建一个该实现类 里面封装了advised中的MethodInterceptor的AOP联盟中定义的接口
        enhancer.setCallback(new DynamicAdvisedInterceptor(advised));
        return enhancer.create();
    }


    /**
     * 注意此处的MethodInterceptor是cglib中的接口，advised中的MethodInterceptor的AOP联盟中定义的接口，因此定义此类做适配
     * 而这里定义的DynamicAdvisedInterceptor拦截器里的增强方法
     * 是通过封装调用advised中的MethodInterceptor的AOP联盟中定义的接口来实现的
     */
    private static class DynamicAdvisedInterceptor implements MethodInterceptor {
        private final AdvisedSupport advised;

        private DynamicAdvisedInterceptor(AdvisedSupport advised) {
            this.advised = advised;
        }

        @Override
        public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            // 获取目标对象
            Object target = advised.getTargetSource().getTarget();
            Class<?> targetClass = target.getClass();
            Object retVal = null;
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
            CglibMethodInvocation methodInvocation = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy);
            if (chain == null || chain.isEmpty()) {
                retVal = methodProxy.invoke(target, args);
            } else retVal = methodInvocation.proceed();
            return retVal;
        }
    }

    /**
     * 实际调用目标对象方法的类
     */
    private static class CglibMethodInvocation extends ReflectiveMethodInvocation {
        //cglib创建代理对象的核心封装类吧
        private final MethodProxy methodProxy;

        public CglibMethodInvocation(Object proxy, Object target, Method method,
                                     Object[] arguments, Class<?> targetClass,
                                     List<Object> interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) {
            super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);
            this.methodProxy = methodProxy;
        }

        //执行真正对象的方法
        @Override
        public Object proceed() throws Throwable {
            return super.proceed();
        }
    }
}
